package tk.xboot.boot.web;

import java.io.Closeable;


/**
 * A simple pairing of the index of an intercepted stream with the
 * stream-type object which will produce or consume the data sent over the
 * intercepted stream.
 *
 * @param <T>
 *     The type of object which will produce or consume the data sent over the
 *     intercepted stream. Usually, this will be either InputStream
 *     or OutputStream.
 */

public class InterceptedStream<T extends Closeable> {


    /**
     * The index of the Guacamole stream being intercepted.
     */
    private final String index;

    /**
     * The stream which will produce or consume the data sent over the
     * intercepted Guacamole stream.
     */
    private final T stream;

    /**
     * The exception which prevented the stream from completing successfully,
     * if any. If the stream completed successfully, or has not encountered any
     * exception yet, this will be null.
     */
    private Exception streamError = null;

    /**
     * Creates a new InterceptedStream which associated the given Guacamole
     * stream index with the given stream object.
     *
     * @param index
     *     The index of the Guacamole stream being intercepted.
     *
     * @param stream
     *     The stream which will produce or consume the data sent over the
     *     intercepted Guacamole stream.
     */
    public InterceptedStream(String index, T stream) {
        this.index = index;
        this.stream = stream;
    }

    /**
     * Returns the index of the Guacamole stream being intercepted.
     *
     * @return
     *     The index of the Guacamole stream being intercepted.
     */
    public String getIndex() {
        return index;
    }

    /**
     * Returns the stream which will produce or consume the data sent over the
     * intercepted Guacamole stream.
     *
     * @return
     *     The stream which will produce or consume the data sent over the
     *     intercepted Guacamole stream.
     */
    public T getStream() {
        return stream;
    }

    /**
     * Reports that this InterceptedStream did not complete successfully due to
     * the given GuacamoleException, which could not be thrown at the time due
     * to asynchronous handling of the stream contents.
     *
     * @param streamError
     *     The exception which prevented the stream from completing
     *     successfully.
     */
    public void setStreamError(Exception streamError) {
        this.streamError = streamError;
    }


    /**
     * Returns whether an error has prevented this InterceptedStream from
     * completing successfully. This will return false if the stream has
     * completed successfully OR if the stream simply has not yet completed.
     *
     * @return
     *     true if an error has prevented this InterceptedStream from
     *     completing successfully, false otherwise.
     */
    public boolean hasStreamError() {
        return streamError != null;
    }

    /**
     * Returns a GuacamoleException which describes why this InterceptedStream
     * did not complete successfully.
     *
     * @return
     *     An exception describing the error that prevented the stream from
     *     completing successfully, or null if no such error has occurred.
     */
    public Exception getStreamError() {
        return streamError;
    }

}
